#coding=utf-8
from urllib.request import urlopen
from urllib.parse import quote
from bs4 import BeautifulSoup
import smtplib  
from email.mime.text import MIMEText  
from email.header import Header
import pymongo
# 使用线程优化效率
import time  
import threading
import sys
import re

# 邮件发送参数
sender = 'sender email addr' 
receiver = 'receiver email addr' 
subject = '考试日程提醒' 
smtpserver = 'smtp.163.com' 
username = 'your username' 
password = 'your password' 

# 查找目标
url_base = 'http://ccst.jlu.edu.cn/'
target_text = '2012级'
sleep_time_normal = 15*60	# 设置15分钟检查一次
sleep_time_high = 5			# 设置5秒钟一次
global sleep_time

# 判断一个字符是否是汉字
def is_chinese(uchar):
	reChinese = re.compile('[\u4e00-\u9fa5]')
	if reChinese.search(uchar) != None:
		return True
	else:
		return False

# 处理url中的中文字符问题
def turn_chinese_to_base64(string):
	result = '';
	for i in range(len(string)):
		if(is_chinese(string[i])):
			# 把字符转为gbk
			result += quote(string[i].encode('gbk')) 
		else:
			result += string[i]
	return result

def getHtml(url):
	url = turn_chinese_to_base64(url)
	url = url_base + url
	try:
		page = urlopen(url, timeout = 10)
	except:
		html = None
	else:
		html = page.read()
		html = html.decode('gbk')
	return html

def sendEmail(smtp, title, text, notes):
	global sleep_time
	msg = MIMEText(text,'html','utf-8') 
	msg['Subject'] = Header(subject + ' - ' + title, 'utf-8')  
	try:
		smtp.sendmail(sender, receiver, msg.as_string()) 
		notes.update({'title':title}, {'title':title, 'sended': 1})
		print("%s had been sended" %(title))
	except:
		print("[ERROR] error in sending %s" %(title))
		sleep_time = sleep_time_high

def checkNotSendedEmail(smtp, notes):
	print("检查尚未发送成功的邮件")
	unSended = notes.find({'sended': 0})
	for item in unSended:
		# 为了保证发送的成功率，在这不新开线程
		sendEmail(smtp, item['title'], item['html'], notes)

def newTask():

	# 登录邮箱系统
	smtp = smtplib.SMTP()  
	smtp.connect('smtp.163.com')  
	smtp.login(username, password)
	# 初始化开始地址
	target = '?mod=info&act=search&kw=考试&x=0&y=1'
	# 同时开启4个线程
	thread_list = list()

	# 循环执行标记
	flag = True

	# 初始化数据库
	db = pymongo.MongoClient()
	notes = db.ccst_db.notes

	while(flag):
		# 初始化
		tid = None
		html = getHtml(target)
		flag = False
		# 检查是否获取到html元素
		if html == None:
			break

		soup = BeautifulSoup(html)

		# 查找目标结果集合
		target_items = soup.find(class_='list').ul.find_all('a')
		# 将结果转化为字符串
		result = ''
		for target_item in target_items:
			if target_text in target_item.text:
				if notes.find_one({"title": target_item.text}) == None:
					
					# 设置标志位，因为网页有变动
					flag = True
					
					# 打开通知具体页面
					target_url = target_item.attrs['href']
					target_html = getHtml(target_url)
					#print(target_html)
					target_soup = BeautifulSoup(target_html)
					result = str(target_soup.find(class_='list').div)
					# 如果没有当前记录，保存到数据库
					post = {"title": target_item.text,
							"url": target_item.attrs['href'],
							"html": result,
							"sended": 0}
					notes.insert(post)

					# 等待上一次线程执行结束
					if tid != None:
						tid.join()

					# 新建发送电子邮件的线程
					tid = threading.Thread(target=sendEmail, args=(smtp, target_item.text, result, notes))
					tid.setDaemon(True)
					tid.start()

		if flag:
			print("网页有新消息")
		else:
			print("网页无新消息")

		if soup.find(class_="pagestring").find('a',text="下一页") == None:
			break
		else:
			target = soup.find(class_="pagestring").find('a',text="下一页").attrs['href']

	# 确保最后线程执行完成
	if tid != None:
		tid.join()
	# 检查发送失败的邮件
	checkNotSendedEmail(smtp, notes)
	# 退出邮箱系统
	smtp.quit()
# 主线程
if __name__=='__main__':
	global sleep_time
	try:
		while True:
			# 重置系统挂起时间
			sleep_time = sleep_time_normal
			newTask()
			time.sleep(sleep_time)
	except KeyboardInterrupt:
		print('程序结束')
		sys.exit(0)
